using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using System;
using System.Timers;
using System.Collections.Generic;



namespace RaceGame2013
{
    public class Voertuig : IVoertuig
    {
        // Test
        public List<Kogel> kogels = new List<Kogel>();

        // Standard attributes
        public Wapen wapen;
        public float speed;
        public float damage;
        public int player;
        public int laps;
        public float gas = 100;
        public float aMove;
        public float Velocity;
        public float carSpeed;
        public Boolean[] checkPoint = new Boolean[4];
        bool aCollision = false;

        // Other attributes
        public Rectangle voertuigCollisionBox;
        public Texture2D voerTuigtexture;
        public Vector2 Position = new Vector2(280, 150);
        // Holding the X and Y history 
        public Vector2 oldPosition;
        public float rotation = 0;
        public int height;
        public int width;
        public double scale = 0.2;//.09;
         
        // Check vars for the pitstop
        Boolean isOnPitstop = false;
        // Count to ten to get the health 
        Timer aTimer = new Timer(10000);

        // Health
        public float health;
        public Vector2 healthbarposition = new Vector2(20, 40);
        public Texture2D healthbartexture;
        public Rectangle healthrectangle;

        // GraphicsDeviceManager
        public GraphicsDeviceManager graphics;

        // Reference to the track
        public Track track;

        // Reference to spritebatch
        public SpriteBatch spriteBatch;

        // Reference to ContentManager Content
        public ContentManager Content;


        // Default constructor
        public Voertuig()
        {
            // Set standart health
            health = 100;
            wapen = new Pistool();
            player = 1;

        }

        // Constructor
        public Voertuig(ContentManager content, GraphicsDeviceManager graphics, SpriteBatch spriteBatch, Track track)
        {
            // Set standart health
            health = 100;
            wapen = new Pistool();
            player = 1;
                            // set current rotation
            rotation = 180;

            // GraphicsDeviceManager
            this.graphics = graphics;

            // Reference to the track
            this.track = track;

            // Reference to spritebatch
            this.spriteBatch = spriteBatch;

            // Reference to the Main ContentManager
            this.Content = content;
        }

        // Overloaded Constructor
        public Voertuig(ContentManager content, GraphicsDeviceManager graphics, SpriteBatch spriteBatch, Track track, Vector2 pos, Viewport viewport, int play)
        {
            // Set standart health
            health = 100;
            wapen = new Pistool();

            this.player = play;

            // Set collision box
            voertuigCollisionBox = new Rectangle((int)this.Position.X, (int)this.Position.Y, width, height);
            Position = new Vector2(55, 400);

            // GraphicsDeviceManager
            this.graphics = graphics;

            // Reference to the track
            this.track = track;

            // Refence to spriteBatch
            this.spriteBatch = spriteBatch;

            // Set the checkpoints to zero
            for (int i = 0; i < checkPoint.Length; i++) 
            {
                // 
                checkPoint[i] = false;
            }


            // Reference to the Main ContentManager
            this.Content = content;
        }

        // load content
        public virtual void LoadContent()
        {
            // Load the car
            voerTuigtexture = Content.Load<Texture2D>("Car");
            // Later for the health bar
            //healthbartexture = Content.Load<Texture2D>(@"images/HealthBar");

            // Scale the height of the car appropriately
            width = (int)(voerTuigtexture.Width * scale);
            height = (int)(voerTuigtexture.Height * scale);

            // Set collision box
            voertuigCollisionBox = new Rectangle((int)this.Position.X, (int)this.Position.Y, width, height);

        }

        // The update method
        public void Update(GameTime gameTime)
        {
            GamePadState aGamePad = GamePad.GetState(PlayerIndex.One);
            KeyboardState aKeyBoard = Keyboard.GetState();

            // Rotate the car sprite with the Left Thumbstick or the up and down arrows
            rotation += (float)(aGamePad.ThumbSticks.Left.X * 3.0f * gameTime.ElapsedGameTime.TotalSeconds);

            // Setup the movement increment
            aMove = (int)(200 * gameTime.ElapsedGameTime.TotalSeconds)  * speed ;

            // Collision checks for the layer
            CollisionOccurred((int)aMove);


            // Check if player 1
            if (player == 1)
            {
                if ((aKeyBoard.IsKeyDown(Keys.A) == true))
                {
                    rotation -= (float)((1.5f * Velocity) * gameTime.ElapsedGameTime.TotalSeconds);
                }
                else if (aKeyBoard.IsKeyDown(Keys.D) == true)
                {
                    rotation += (float)((1.5f * Velocity) * gameTime.ElapsedGameTime.TotalSeconds);
                }

                // Drive
                KeyboardState keyState = Keyboard.GetState();


                if ((!aCollision) && (aKeyBoard.IsKeyDown(Keys.W)) && (this.gas > 0))
                {
                    // Move the sprite
                    Velocity += (float)(speed * gameTime.ElapsedGameTime.TotalSeconds);

                    // Gas is running up
                    gas -= (float)(speed * gameTime.ElapsedGameTime.TotalSeconds);

                    if (Velocity > speed)
                    {
                        Velocity = speed;
                    }

                    Position.X += (float)(Velocity * Math.Cos(rotation));
                    Position.Y += (float)(Velocity * Math.Sin(rotation));
                    voertuigCollisionBox.X = (int)Position.X;
                    voertuigCollisionBox.Y = (int)Position.Y;
                }
                else if (Velocity > 0f)
                {
                    Velocity += (float)(speed * -gameTime.ElapsedGameTime.TotalSeconds);

                    if (Velocity < 0.0000001f)
                    {
                        Velocity = 0;

                    }

                    Position.X += (float)(Velocity * Math.Cos(rotation));
                    Position.Y += (float)(Velocity * Math.Sin(rotation));
                    voertuigCollisionBox.X = (int)Position.X;
                    voertuigCollisionBox.Y = (int)Position.Y;

                }



                // Reverse
                if ((!aCollision) && (aKeyBoard.IsKeyDown(Keys.S)) && (this.gas > 0))
                {
                    // Move the sprite
                    Velocity -= (float)(speed * gameTime.ElapsedGameTime.TotalSeconds);

                    // Gas is running up
                    gas -= (float)(speed * gameTime.ElapsedGameTime.TotalSeconds);

                    if (Velocity < -speed)
                    {
                        Velocity = -speed;
                    }


                    Position.X += (float)(Velocity * Math.Cos(rotation));
                    Position.Y += (float)(Velocity * Math.Sin(rotation));
                    voertuigCollisionBox.X = (int)Position.X;
                    voertuigCollisionBox.Y = (int)Position.Y;
                }
                else if (Velocity < 0f)
                {
                    Velocity += (float)(speed * gameTime.ElapsedGameTime.TotalSeconds);
                    if (Velocity > -0.0000001f)
                    {
                        Velocity = 0;

                    }
                    Position.X += (float)(Velocity * Math.Cos(rotation));
                    Position.Y += (float)(Velocity * Math.Sin(rotation));
                    voertuigCollisionBox.X = (int)Position.X;
                    voertuigCollisionBox.Y = (int)Position.Y;

                }

               
                // Shoot bullet
                if (aKeyBoard.IsKeyDown(Keys.Space))
                {
                    // Shoot
                    Shoot(gameTime);
                }
            }

            if (player == 2)
            {
                if (aKeyBoard.IsKeyDown(Keys.Left) == true)
                {
                    rotation -= (float)((1.5f * Velocity) * gameTime.ElapsedGameTime.TotalSeconds);
                }
                if (aKeyBoard.IsKeyDown(Keys.Right) == true)
                {
                    rotation += (float)((1.5f * Velocity) * gameTime.ElapsedGameTime.TotalSeconds);
                }

                if ((!aCollision) && (aKeyBoard.IsKeyDown(Keys.Up)) && (this.gas > 0))
                {
                    // Move the sprite
                    Velocity += (float)(speed * gameTime.ElapsedGameTime.TotalSeconds);

                    // Gas is running up
                    gas -= (float)(speed * gameTime.ElapsedGameTime.TotalSeconds);

                    if (Velocity > speed)
                    {
                        Velocity = speed;
                    }
                    Position.X += (float)(Velocity * Math.Cos(rotation));
                    Position.Y += (float)(Velocity * Math.Sin(rotation));
                    voertuigCollisionBox.X = (int)Position.X;
                    voertuigCollisionBox.Y = (int)Position.Y;
                }
                else if (Velocity > 0f)
                {
                    Velocity += (float)(speed * -gameTime.ElapsedGameTime.TotalSeconds);
                    if (Velocity < 0.0000001f)
                    {
                        Velocity = 0;
                    }

                    Position.X += (float)(Velocity * Math.Cos(rotation));
                    Position.Y += (float)(Velocity * Math.Sin(rotation));
                    voertuigCollisionBox.X = (int)Position.X;
                    voertuigCollisionBox.Y = (int)Position.Y;
                }


                // Driving reverse
                if ((!aCollision) && (aKeyBoard.IsKeyDown(Keys.Down)) && (this.gas > 0))
                {
                    // Move the sprite
                    Velocity -= (float)(speed * gameTime.ElapsedGameTime.TotalSeconds);
                    // Gas is running up
                    gas -= (float)(speed * gameTime.ElapsedGameTime.TotalSeconds);

                    if (Velocity < -speed)
                    {
                        Velocity = -speed;
                    }

                    Position.X += (float)(Velocity * Math.Cos(rotation));
                    Position.Y += (float)(Velocity * Math.Sin(rotation));
                    voertuigCollisionBox.X = (int)Position.X;
                    voertuigCollisionBox.Y = (int)Position.Y;
                }
                else if (Velocity < 0f)
                {
                    Velocity += (float)(speed * gameTime.ElapsedGameTime.TotalSeconds);
                    if (Velocity > -0.0000001f)
                    {
                        Velocity = 0;

                    }
                    Position.X += (float)(Velocity * Math.Cos(rotation));
                    Position.Y += (float)(Velocity * Math.Sin(rotation));
                    voertuigCollisionBox.X = (int)Position.X;
                    voertuigCollisionBox.Y = (int)Position.Y;

                }

                // Shoot bullet
                if (aKeyBoard.IsKeyDown(Keys.RightControl))
                {
                    // Shoot
                    Shoot(gameTime);
                }
            }


            // Update the bullets so they can move 
            foreach (Kogel kogel in kogels)
            {
                kogel.Update(gameTime);
            }

        }

        // Shoot function
        private void Shoot(GameTime gameTime)
        {
            // Setup the movement increment
            int aMove = (int)(200 * gameTime.ElapsedGameTime.TotalSeconds);
            // Make a nieuw bullet and add them to the list
            Kogel nieuwKogel = new Kogel(Content,spriteBatch);
            nieuwKogel.ActivateBullet(new Vector2((float)(aMove * Math.Cos(rotation)), (float)(aMove * Math.Sin(rotation))), this.Position);
            
            nieuwKogel.isActive = true;
            kogels.Add(nieuwKogel);         
        }


        private bool CollisionOccurred(int aMove)
        {
            // Calculate 
            //Calculate the Position of the Car and create the collision Texture. This texture will contain
            //all of the pixels that are directly underneath the sprite currently on the Track image.
            float aXPosition = (float)(-this.width / 2 + this.Position.X + aMove * Math.Cos(this.rotation));
            float aYPosition = (float)(-this.height / 2 + this.Position.Y + aMove * Math.Sin(this.rotation));
            Texture2D aCollisionCheck = CreateCollisionTexture(aXPosition, aYPosition);

            //Use GetData to fill in an array with all of the Colors of the Pixels in the area of the Collision Texture
            int aPixels = this.width * this.height;
            Color[] myColors = new Color[aPixels];
            aCollisionCheck.GetData<Color>(0, new Rectangle((int)(aCollisionCheck.Width / 2 - this.width / 2),
                (int)(aCollisionCheck.Height / 2 - this.height / 2), this.width, this.height), myColors, 0, aPixels);

            aCollision = false;


            // Set the timer on 
            foreach (Color aColor in myColors)
            {
                //If one of the pixels in that area is not Gray, then the sprite is moving
                //off the allowed movement area
                // Check if the car is riding over the grass
                if (aColor == Color.Green)
                {
                    this.speed = carSpeed/4;
                    break;
                }
                // Check if the car is driving on the road
                if (aColor == Color.Gray)
                {
                    this.speed = carSpeed;
                    break;
                }

                // Check if the car has drived over the first checkpoint
                if (aColor == Color.Black)
                {
                    if ((checkPoint[1] == false) && (checkPoint[2] == false) && (checkPoint[3] == false))
                    {
                        checkPoint[0] = true;
                    }
                }

                // Check if the car has drived over the second checkpoint
                if (aColor == Color.DarkGray)
                {
                    if ((checkPoint[0] == true) && (checkPoint[2] == false) && (checkPoint[3] == false))
                        checkPoint[1] = true;
                }

                // Check if the car has drived over the third checkpoint
                if (aColor == Color.DarkSlateGray)
                {
                    if ((checkPoint[0] == true) && (checkPoint[1] == true) && (checkPoint[3] == false))
                        checkPoint[2] = true;
                }

                // Check if the car has drived over the fourth checkpoint
                if (aColor == Color.DimGray)
                {
                    if ((checkPoint[0] == true) && (checkPoint[1] == true) && (checkPoint[2] == true))
                    {
                        checkPoint[3] = true;
                        laps += 1;
                    }

                    // Set all the checkpoints back to false
                    for (int i = 0; i < checkPoint.Length; i++)
                    {
                        checkPoint[i] = false;
                    }
                    
                }

                // Check if the car is hit by a tree
                if (aColor == Color.Blue)
                {
                    //Console.WriteLine("Drived over blue");
                    speed = -carSpeed/2;
                   // health = health-0.1f;
                }
                // Check if the car is driving on the road
                if ((isOnPitstop == false) && (aColor == Color.Yellow))
                {
                    // Pitstop check
                    isOnPitstop = true;

                    // Hook up the Elapsed event for the timer.
                    aTimer.Elapsed += new ElapsedEventHandler(Repair);

                    //Enable the timer
                    aTimer.Enabled = true;
                    break;
                }
                
                // Check if the the cars is hit by a bullet
                if (aColor == Color.Red)
                {
                    Console.WriteLine("Player:{0} was hit by a bullet!", this.player);
                }
            }
            return aCollision;
        }


        // If ten seconds are over its now time to give the power and healt back again
        private void Repair(object source, ElapsedEventArgs e)
        {
            // Ne
            this.health = 100;
            this.damage = 100;
            this.gas = 100;

            Console.WriteLine("The health is back again");

            // Stop the timer
            aTimer.Enabled = false;
            isOnPitstop = false;

            // Remove the event handler
            aTimer.Elapsed -= new ElapsedEventHandler(Repair);
        }

        //Create the Collision Texture that contains the rotated Track image for determing
        //the pixels beneath the Car srite.
        private Texture2D CreateCollisionTexture(float theXPosition, float theYPosition)
        {
            //Grab a square of the Track image that is around the Car
            graphics.GraphicsDevice.SetRenderTarget(track.mTrackRender);
            graphics.GraphicsDevice.Clear(ClearOptions.Target, Color.Red, 0, 0);

            spriteBatch.Begin();
            spriteBatch.Draw(track.mTrack, new Rectangle(0, 0, this.width + 100, this.height + 100),
                new Rectangle((int)(theXPosition - 50),
                (int)(theYPosition - 50), this.width + 100, this.height + 100), Color.White);
            spriteBatch.End();

            //graphics.GraphicsDevice.ResolveRenderTarget(0);
            graphics.GraphicsDevice.SetRenderTarget(null);

            Texture2D aPicture = track.mTrackRender;


            //Rotate the snapshot of the area Around the car sprite and return that 
            graphics.GraphicsDevice.SetRenderTarget(track.mTrackRenderRotated);
            graphics.GraphicsDevice.Clear(ClearOptions.Target, Color.Red, 0, 0);

            spriteBatch.Begin();
            spriteBatch.Draw(aPicture, new Rectangle((int)(aPicture.Width / 2), (int)(aPicture.Height / 2),
                aPicture.Width, aPicture.Height), new Rectangle(0, 0, aPicture.Width, aPicture.Width),
                Color.White, -this.rotation, new Vector2((int)(aPicture.Width / 2), (int)(aPicture.Height / 2)),
                SpriteEffects.None, 0);
            spriteBatch.End();

            //graphics.GraphicsDevice.ResolveRenderTarget(0);
            graphics.GraphicsDevice.SetRenderTarget(null);

            Texture2D mTrackRotatedTexture = (Texture2D)track.mTrackRenderRotated;

            return mTrackRotatedTexture;
        }


        // Draw
        public virtual void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(voerTuigtexture, new Rectangle((int)Position.X, (int)Position.Y, width, height),
                    new Rectangle(0, 0, voerTuigtexture.Width, voerTuigtexture.Height), Color.White, rotation,
                    new Vector2(voerTuigtexture.Width / 2, voerTuigtexture.Height / 2), SpriteEffects.None, 0);


            foreach (Kogel kogel in kogels)
            {
                kogel.Draw();
            }
        }


    }

}

